/*
 * MIT License
 *
 * Copyright (c) 2020 wen.gu <454727014@qq.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/***************************************************************************
 * Name: xdialer.h
 *
 * Purpose: dialer base API define
 *
 * Developer:
 *   wen.gu , 2023-07-07
 *
 * TODO:
 *
 ***************************************************************************/

#ifndef __XBUS_TRANSPORT_XDIALER_H__
#define __XBUS_TRANSPORT_XDIALER_H__

#include <string>
#include <memory>
#include <functional>

#include "xbus/core/xtype.h"
#include "xbus/core/xerror.h"
#include "xbus/osal/xthread.h"
#include "xbus/transport/xmessage_queue.h"
#include "xbus/transport/xio.h"

namespace xbus::transport {

class XDialer {
public:
    using XComId = core::XComId;
    using XErrC = core::XErrC;
    using XMessagePtr = core::XMessagePtr;
    using XDialerPtr = std::shared_ptr<XDialer>;
public:
    using OnConnectStatusHandler = std::function<void(bool is_connected)>;
    using DataFillHandler = std::function<XErrC(uint8_t* payload_buf, uint32_t size)>;
public:
    XDialer(const std::string& url, const std::string& trans_proto);
    virtual ~XDialer();
public:
    virtual const std::string& trans_protocol() const { return trans_protocol_; }
    virtual XErrC initialize(int32_t send_priority, int32_t recv_priority, uint32_t max_send_queue_size, uint32_t max_recv_queue_size);
public:
    virtual XErrC start();
    virtual XErrC stop();

public: /** only support connection-oriented transport layer implementation(e.g uds, tcp) */
    virtual void set_status_handler(OnConnectStatusHandler&& status_handler) { on_connected_status_ = status_handler; }
    virtual bool is_reconnection_enabled() const { return reconnection_enabled_; }
    virtual void enable_reconnection(bool enable) { reconnection_enabled_ = enable; }

public: /** sender API */
    
    virtual XErrC send(uint8_t type, uint32_t payload_size, const uint8_t* payload_data);

    /** this API will alloc message with 'payload_size' and call 'fill_handler' method to fill payload to message */
    virtual XErrC send(uint8_t type, uint32_t payload_size, DataFillHandler&& fill_handler);

    virtual XErrC flush(int32_t timeout_ms = core::WaitType::WaitForever); //wait for all message in sender to be sent.

public: /** receiver API */
    /** timeout_ms: see also 'class Timeout',
     * NoWait: if haven't message received, then return immediately
     * WaitForever: if haven't message received, then recv() will be block until receive a message or the XEndpoint is stopped
     * > 0: if haven't message received, then recv() will be block until receive a message or the XEndpoint is stopped or timeout
    */
    virtual core::XResult<XMessagePtr> recv(int32_t timeout_ms = core::WaitType::WaitForever); 

protected:
    virtual XErrC send(XMessagePtr msg_ptr);
protected:
    bool reconnection_enabled_;
    std::string url_;
    std::string trans_protocol_;
    std::unique_ptr<XIO> io_ptr_;
    OnConnectStatusHandler on_connected_status_;
};

} //namespace xbus::transport


#endif /** !__XBUS_TRANSPORT_XDIALER_H__ */